home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 43 / Amiga Format CD43 (1999)(Future Publishing)(GB)(Track 1 of 2)[!][issue 1999-09].iso / -serious- / archivers / xpk / xpk_source / prefs / xpkmasterprefs.c < prev   
C/C++ Source or Header  |  1999-06-14  |  17KB  |  644 lines

  1. #define NAME        "XpkMasterPrefs"
  2. #define DISTRIBUTION    "(Freeware) "
  3. #define REVISION    "18"
  4. //#define DEBUG
  5.  
  6. /* Programmheader
  7.  
  8.     Name:        XpkMasterPrefs
  9.     Author:        SDI
  10.     Distribution:    Freeware
  11.     Description:    xpk prefs loader, like IPrefs
  12.     Compileropts:    -
  13.     Linkeropts:    -gsi (no startup)
  14.  
  15.  1.0   25.12.96 : first Version
  16.  1.1   26.12.96 : nearly redefined xpkprefs structures - a lot of changes
  17.  1.2   27.12.96 : some fixes
  18.  1.3   30.12.96 : did a bit on Recog function
  19.  1.4   02.01.97 : added correctness check of BufPattern
  20.  1.5   11.01.97 : corrected some errors
  21.  1.6   28.02.97 : changed some semaphore specific stuff
  22.  1.7   01.03.97 : added Version info to MainPrefs
  23.  1.8   07.03.97 : fixed RecogFunc
  24.  1.9   24.03.97 : added DEBUG stuff
  25.  1.10  28.03.97 : added last function and ReadArgs
  26.  1.11  02.04.97 : XpkTypeData changed, ListData now internal structure
  27.  1.12  03.04.97 : added DEBUG info, debuged RecogFunction
  28.  1.13  04.04.97 : buffer now 2 K
  29.  1.14  06.06.97 : name pattern no case independant
  30.  1.15  17.06.97 : fixed error, when no name and no filepattern
  31.  1.16  18.06.97 : added filelength check and OR parameter
  32.  1.17  13.08.97 : fixed Enforcer hit
  33.  1.18  16.01.98 : fixed possible design flaw
  34. */
  35.  
  36. /*
  37. How to parse the type list:
  38. - The struct XpkTypeData of the first matching structure is returned.
  39. - If no type matches, the default is returned.
  40. - Scan goes always in linear order from the beginning to end. (and never
  41.   reverse).
  42. - if no file name is given, the xtp_FilePattern field is ignored.
  43. */
  44.  
  45. #include <proto/exec.h>
  46. #include <proto/dos.h>
  47. #include <proto/iffparse.h>
  48. #include <utility/tagitem.h>
  49. #include <prefs/prefhdr.h>
  50. #include <xpk/xpkprefs.h>
  51. #include <exec/memory.h>
  52. #include "SDI_defines.h"
  53. #define SDI_TO_ANSI
  54. #include "SDI_ASM_STD_protos.h"
  55.  
  56.  
  57. /**************************************************************************
  58.  *
  59.  * Standard prefs specific data structure. xps_PrefsData points to this.
  60.  *
  61.  * xssd_TypeList nodes are of type XpkTypeNode.
  62.  *
  63.  * 
  64.  */
  65.  
  66. struct XpkStdSemaphoreData {
  67.   struct List    xssd_TypeList;     /* list of file types */
  68.   ULONG        xssd_Buffer1Size;  /* size of following buffer */
  69.   STRPTR    xssd_Buffer1;       /* pointer to buffer */
  70. };
  71.  
  72. struct XpkTypeNode {
  73.   struct Node        xtn_Node;    /* standard node structure */
  74.   ULONG            xtn_Size;    /* hold complete size to free */
  75.   struct XpkTypePrefs    xtn_TypePrefs;  /* real data */
  76. };
  77.  
  78. #define RECOGBUFSIZE    2048
  79.  
  80. #define PARAM "QUIT/S"
  81.  
  82. #ifdef __MAXON__
  83.   #define __asm
  84.   struct Library *IFFParseBase;
  85. #else
  86.   #define iffparsebase    IFFParseBase
  87. #endif
  88.  
  89. struct DosLibrary *DOSBase;
  90. struct ExecBase *SysBase;
  91.  
  92. void CorrectAdr(APTR pos, APTR mempos);
  93. void DoPrefsCreation(struct XpkPrefsSemaphore *sem);
  94. void ClearTypeList(struct XpkStdSemaphoreData *sem);
  95. void ClearMainPrefs(struct XpkPrefsSemaphore *sem);
  96. struct XpkTypeData * __asm RecogFunc(register __a0 STRPTR buf,
  97. register __a1 STRPTR name, register __d0 ULONG bufsize,
  98. register __d1 ULONG fullsize, register __a2 struct TagItem *);
  99.  
  100. UBYTE CheckHex(STRPTR *data, LONG number);
  101. ULONG CheckBufPattern(STRPTR pattern);
  102. UBYTE GetCharacter(STRPTR pattern);
  103. /* these two return zero, when name matches or defined values, when not */
  104. ULONG CheckPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize);
  105. ULONG MatchBufPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize);
  106. ULONG MatchFileName(STRPTR pattern, STRPTR name);
  107.  
  108. #define MATCHERR_PATTERN_INCORRECT    1
  109. #define MATCHERR_NO_MEMORY        2
  110. #define MATCHERR_BUFFER_TO_SHORT    3
  111. #define MATCHERR_NO_MATCH        4
  112. #define MATCHERR_NO_SIZE_MATCH        5
  113.  
  114. ULONG start(void) /* not named main, to get error with startup code ! */
  115. {
  116.   struct DosLibrary *dosbase;
  117.   struct XpkPrefsSemaphore *semaphore;
  118.   struct Process *task;
  119.   struct Message *msg = 0;
  120.   struct RDArgs *rda;
  121.   LONG quit = 0;
  122.  
  123.   SysBase = (*((struct ExecBase **) 4));
  124.  
  125.   if(!(task = (struct Process *) FindTask(0))->pr_CLI)
  126.   {
  127.     WaitPort(&task->pr_MsgPort);
  128.     msg = GetMsg(&task->pr_MsgPort);
  129.     /* no tooltype check now, so means always start semaphore */
  130.   }
  131.   else
  132.   {
  133.     if((dosbase = (struct DosLibrary *) OpenLibrary("dos.library", 37)))
  134.     {
  135.       DOSBase = dosbase;
  136.       if((rda = ReadArgs(PARAM, &quit, 0)))
  137.         FreeArgs(rda);
  138.       CloseLibrary((struct Library *) dosbase);
  139.     }
  140.     /* does not recognize failed ReadArgs - normal start in this case */
  141.   }
  142.  
  143.   Forbid();
  144.   semaphore = (struct XpkPrefsSemaphore *) FindSemaphore(XPKPREFSSEMNAME);
  145.   if(quit)
  146.   {
  147.     if(semaphore)
  148.     {
  149.       ObtainSemaphoreShared((struct SignalSemaphore *) semaphore);
  150.         Signal(semaphore->xps_MasterTask, SIGBREAKF_CTRL_C);
  151.       ReleaseSemaphore((struct SignalSemaphore *) semaphore);
  152.     }
  153.     Permit();
  154.   }
  155.   else if(!semaphore && (dosbase = (struct DosLibrary *)
  156.   OpenLibrary("dos.library", 37)))
  157.   {
  158.     DOSBase = dosbase;
  159.     if((semaphore = (struct XpkPrefsSemaphore *) AllocMem(sizeof(struct
  160.     XpkPrefsSemaphore) + sizeof(struct XpkStdSemaphoreData), MEMF_PUBLIC|MEMF_CLEAR)))
  161.     {
  162.       struct NotifyRequest *notifyrequest;
  163.  
  164.       struct XpkStdSemaphoreData *sd = (struct XpkStdSemaphoreData *)
  165.        (((STRPTR) semaphore) + sizeof(struct XpkPrefsSemaphore));
  166.         /* both structures are allocated with one AllocMem */
  167.  
  168.       InitSemaphore((struct SignalSemaphore *) semaphore);
  169.  
  170.       semaphore->xps_Semaphore.ss_Link.ln_Type = NT_SEMAPHORE;
  171.       semaphore->xps_Semaphore.ss_Link.ln_Name = XPKPREFSSEMNAME;
  172.       semaphore->xps_PrefsData = sd;
  173. //    semaphore->xps_Version = 0;
  174.       semaphore->xps_PrefsType = XPREFSTYPE_STANDARD;
  175. //    semaphore->xps_ProgressFunc = 0;
  176.       semaphore->xps_RecogSize = RECOGBUFSIZE;
  177.       semaphore->xps_RecogFunc = (struct XpkTypeData *(*)()) RecogFunc;
  178.       semaphore->xps_MasterTask = (struct Task *) task;
  179.  
  180.       sd->xssd_TypeList.lh_Type = NT_USER;
  181.       sd->xssd_TypeList.lh_Head = (struct Node *) &sd->xssd_TypeList.lh_Tail;
  182.       sd->xssd_TypeList.lh_TailPred = (struct Node *) &sd->xssd_TypeList.lh_Head;
  183.  
  184.       AddSemaphore((struct SignalSemaphore *) semaphore);
  185.       Permit();
  186.  
  187.       if((notifyrequest = (struct NotifyRequest *)
  188.       AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR)))
  189.       {
  190.         ULONG signr;
  191.  
  192.         if((signr = AllocSignal(-1L)) != -1)
  193.         {
  194.           notifyrequest->nr_Name = "ENV:xpkmaster.prefs";
  195.           notifyrequest->nr_Flags = NRF_SEND_SIGNAL | NRF_NOTIFY_INITIAL;
  196.           notifyrequest->nr_stuff.nr_Signal.nr_Task = FindTask(0);
  197.           notifyrequest->nr_stuff.nr_Signal.nr_SignalNum = signr;
  198.           if((StartNotify(notifyrequest)) == DOSTRUE)
  199.           {
  200.         ULONG signal = 0;
  201.             while(!(signal & SIGBREAKF_CTRL_C))
  202.               if((signal = Wait(1 << signr | SIGBREAKF_CTRL_C)) & (1 << signr))
  203.             DoPrefsCreation(semaphore);
  204.             EndNotify(notifyrequest);
  205.           }
  206.           FreeSignal(signr);
  207.         }
  208.         FreeMem(notifyrequest, sizeof(struct NotifyRequest));
  209.       }
  210.       ObtainSemaphore((struct SignalSemaphore *) semaphore);
  211.       RemSemaphore((struct SignalSemaphore *) semaphore);
  212.       ClearTypeList((struct XpkStdSemaphoreData *) semaphore->xps_PrefsData);
  213.       ClearMainPrefs(semaphore);
  214.  
  215.       FreeMem(semaphore, sizeof(struct XpkPrefsSemaphore) +
  216.         sizeof(struct XpkStdSemaphoreData));
  217.     }
  218.     else
  219.       Permit();
  220.     CloseLibrary((struct Library *) dosbase);
  221.   }
  222.   else
  223.     Permit();
  224.  
  225.   if(msg)
  226.   {
  227.     Forbid();
  228.     ReplyMsg(msg);
  229.   }
  230.  
  231.   return 0;
  232. }
  233.  
  234. /* changes relative addresses into normal ones */
  235. void CorrectAdr(APTR pos, APTR mempos)
  236. {
  237.   if(*(ULONG *)pos)
  238.     *(ULONG *)pos += (ULONG) mempos;
  239. }
  240.  
  241. void ClearTypeList(struct XpkStdSemaphoreData *sd)
  242. {
  243.   struct Node *n;
  244.  
  245.   while((n = RemHead(&sd->xssd_TypeList)))
  246.     FreeMem(n, ((struct XpkTypeNode *) n)->xtn_Size);
  247. }
  248.  
  249. void ClearMainPrefs(struct XpkPrefsSemaphore *sem)
  250. {
  251.   struct XpkStdSemaphoreData *sd = (struct XpkStdSemaphoreData *) sem->xps_PrefsData;
  252.   if(sd->xssd_Buffer1)
  253.     FreeMem(sd->xssd_Buffer1, sd->xssd_Buffer1Size);
  254.   sem->xps_MainPrefs = 0;
  255.   sd->xssd_Buffer1Size = 0;
  256.   sd->xssd_Buffer1 = 0;
  257. }
  258.  
  259. void DoPrefsCreation(struct XpkPrefsSemaphore *sem)
  260. {
  261.   struct Library *iffparsebase;
  262.   struct ContextNode  *cn;
  263.   struct IFFHandle *iff;
  264.   ULONG prefsversion = 0;
  265.  
  266.   ObtainSemaphore(&sem->xps_Semaphore);
  267.  
  268.   ClearTypeList((struct XpkStdSemaphoreData *) sem->xps_PrefsData);
  269.   ClearMainPrefs(sem);
  270.  
  271.   if(!(iffparsebase = OpenLibrary("iffparse.library", 37)))
  272.     return;
  273.  
  274. #ifdef __MAXON__
  275.   IFFParseBase = iffparsebase;
  276. #endif
  277.  
  278.   if((iff = AllocIFF()))
  279.   {
  280.     if((iff->iff_Stream = Open("ENV:xpkmaster.prefs", MODE_OLDFILE)))
  281.     {
  282.       InitIFFasDOS(iff);
  283.       if(!OpenIFF(iff, IFFF_READ))
  284.       {
  285.     LONG a[] = { ID_PREF, ID_PRHD, ID_PREF, ID_XPKT, ID_PREF, ID_XPKM};
  286.     if(!StopChunks(iff, a, 3))
  287.     {
  288.       ULONG error = 0;
  289.  
  290.       while(!error)
  291.           {
  292.             if(ParseIFF(iff,IFFPARSE_SCAN))
  293.               break;
  294.  
  295.             cn = CurrentChunk(iff);
  296.  
  297.         switch(cn->cn_ID)
  298.         {
  299.         case ID_PRHD:
  300.           {
  301.             struct PrefHeader prh;
  302.             ReadChunkBytes(iff, &prh, sizeof(struct PrefHeader));
  303.             prefsversion = prh.ph_Version;
  304.     /* use this, when internal version is greater than one. In this
  305.        case the value is version of XPKT chunks */
  306.           } break;
  307.         case ID_XPKT:
  308.           {
  309.             struct XpkTypeNode *buf;
  310.         ULONG size;
  311.             size = cn->cn_Size + sizeof(struct Node) + sizeof(ULONG);
  312.             if((buf = (struct XpkTypeNode *) AllocMem(size, MEMF_PUBLIC|MEMF_CLEAR)))
  313.             {
  314.           struct XpkTypePrefs *pref = &buf->xtn_TypePrefs;
  315.  
  316.               ReadChunkBytes(iff, pref, cn->cn_Size);
  317.           CorrectAdr(&pref->xtp_NamePattern, pref);
  318.           CorrectAdr(&pref->xtp_FilePattern, pref);
  319.           CorrectAdr(&pref->xtp_TypeName, pref);
  320.           CorrectAdr(&pref->xtp_PackerData, pref);
  321.           buf->xtn_Node.ln_Name = pref->xtp_TypeName;
  322.           buf->xtn_Node.ln_Type = NT_USER;
  323.           buf->xtn_Size = size;
  324.           pref->xtp_PackerData->xtd_Memory = 0;
  325.           pref->xtp_PackerData->xtd_MemorySize = 0;
  326.           AddTail(&((struct XpkStdSemaphoreData *)sem->xps_PrefsData)->xssd_TypeList, (struct Node *) buf);
  327.             }
  328.             else error = 1;
  329.           } break;
  330.         case ID_XPKM:
  331.           {
  332.         struct XpkMainPrefs *pref;
  333.         struct XpkStdSemaphoreData *sd =
  334.           (struct XpkStdSemaphoreData *) sem->xps_PrefsData;
  335.         struct XpkTypeData *p;
  336.  
  337.         ClearMainPrefs(sem);
  338.  
  339.             if((pref = (struct XpkMainPrefs *) AllocMem(cn->cn_Size, MEMF_PUBLIC|MEMF_CLEAR)))
  340.             {
  341.               ReadChunkBytes(iff, pref, cn->cn_Size);
  342.           CorrectAdr(&pref->xmp_DefaultType, pref);
  343.           p = pref->xmp_DefaultType;
  344.     /* XpkTypeData newer than version 0 may be incorrect, so set to 0 */
  345.           p->xtd_Version = 0;
  346.           p->xtd_Memory = 0;
  347.           p->xtd_MemorySize = 0;
  348.           sem->xps_MainPrefs = pref;
  349.                   sd->xssd_Buffer1Size = cn->cn_Size;
  350.                   sd->xssd_Buffer1 = (STRPTR) pref;
  351.         }
  352.         else error = 1;
  353.           } break;
  354.         }
  355.       }
  356.     }
  357.         CloseIFF(iff);
  358.       }
  359.       Close(iff->iff_Stream);
  360.     }
  361.     FreeIFF(iff);
  362.   }
  363.   CloseLibrary(IFFParseBase);
  364.   ReleaseSemaphore(&sem->xps_Semaphore);
  365. }
  366.  
  367. UBYTE CheckHex(STRPTR *data, LONG number)
  368. {
  369.   LONG num;
  370.   do
  371.   {
  372.     num = number;
  373.     while(num-- && isxdigit(*((*data)++)))
  374.       ;
  375.     if(++num)
  376.       return MATCHERR_PATTERN_INCORRECT;
  377.   } while(isxdigit(**data));
  378.   return 0;
  379. }
  380.  
  381. /* return 0, when pattern is valid */
  382. ULONG CheckBufPattern(STRPTR pattern)
  383. {
  384.   while(*pattern)
  385.   {
  386.     ULONG a;
  387.     STRPTR s;
  388.     
  389.     s = pattern;
  390.  
  391.     switch(*(pattern++))
  392.     {
  393.     case 'l': a = 1; break;
  394.     case 'h': a = 1; break;
  395.     case 'm': a = 1; break;
  396.     case 'v': a = 2; break;
  397.     case 'r': a = 4; break;
  398.     case 'g': a = 4; break;
  399.     case 's': a = 2; break;
  400.     case '|': a = 0; break;
  401.     default: return MATCHERR_PATTERN_INCORRECT; break;
  402.     }
  403.     if(a && CheckHex(&pattern, a))
  404.       return MATCHERR_PATTERN_INCORRECT;
  405.  
  406.     if((*s == 'm' && (pattern-s) > 5) ||
  407.     ((*s == 'l' || *s == 'h') && (pattern-s) > 9))
  408.       return MATCHERR_PATTERN_INCORRECT;
  409.     /* only word data for 'm' and longword for 'l' and 'h' + 1 '.' */
  410.   }
  411.  
  412.   return 0;
  413. }
  414.  
  415. UBYTE GetCharacter(STRPTR pattern)
  416. {
  417.   UBYTE i = 0, c;
  418.   ULONG size = 2;
  419.   while(size--)
  420.   {
  421.     i <<= 4;
  422.     if((c = toupper(*(pattern++))) >= 'A')
  423.       i += c + 10 - 'A';
  424.     else
  425.       i += c - '0';
  426.   }
  427.   return i;
  428. }
  429.  
  430. ULONG CheckPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize)
  431. {
  432.   STRPTR bufpos = buffer;
  433.   ULONG i;
  434.   UBYTE j, k;
  435.   STRPTR errpos, str;
  436.  
  437.   while(pattern && *pattern && *pattern != '|')
  438.   {
  439.     switch(*(pattern++))
  440.     {
  441.     case 'm':
  442.       i = strtoul(pattern, &errpos, 16);
  443.       pattern = errpos; /* first non hex char is next command */
  444.       if(i >= size)
  445.         return MATCHERR_BUFFER_TO_SHORT;
  446.       else
  447.         bufpos = buffer + i;
  448.       break;
  449.     case 'l':
  450.       i = strtoul(pattern, &errpos, 16);
  451.       pattern = errpos; /* first non hex char is next command */
  452.       if(fsize > i)
  453.         return MATCHERR_NO_SIZE_MATCH;
  454.       break;
  455.     case 'h':
  456.       i = strtoul(pattern, &errpos, 16);
  457.       pattern = errpos; /* first non hex char is next command */
  458.       if(fsize < i)
  459.         return MATCHERR_NO_SIZE_MATCH;
  460.       break;
  461.     case 'v':
  462.       while(isxdigit(*pattern))
  463.       {
  464.     j = GetCharacter(pattern); pattern += 2;
  465.         if(bufpos >= buffer + size)
  466.           return MATCHERR_BUFFER_TO_SHORT;
  467.     if(j != *(bufpos++))
  468.       return MATCHERR_NO_MATCH;
  469.       }
  470.       break;
  471.     case 'r':
  472.       while(isxdigit(*pattern))
  473.       {
  474.     errpos = buffer;
  475.     k = GetCharacter(pattern); pattern += 2;
  476.     j = GetCharacter(pattern); pattern += 2;
  477.         while(errpos < buffer + size)
  478.         {
  479.       if(*errpos >= k && *errpos <= j)
  480.         return MATCHERR_NO_MATCH;
  481.       ++errpos;
  482.     }
  483.       }
  484.       break;
  485.     case 'g':
  486.       while(isxdigit(*pattern))
  487.       {
  488.     k = GetCharacter(pattern); pattern += 2;
  489.     j = GetCharacter(pattern); pattern += 2;
  490.         if(bufpos >= buffer + size)
  491.           return MATCHERR_BUFFER_TO_SHORT;
  492.     if(*bufpos < k && *bufpos > j)
  493.       return MATCHERR_NO_MATCH;
  494.     ++bufpos;
  495.       }
  496.       break;
  497.     case 's':
  498.       bufpos = buffer;
  499.       while(isxdigit(*pattern))
  500.       {
  501.         str = pattern;
  502.     j = GetCharacter(str); str += 2;
  503.     while(bufpos < buffer + size && *bufpos != j)
  504.       ++bufpos;
  505.     if(*bufpos == j)
  506.     {
  507.       errpos = ++bufpos;
  508.           while(isxdigit(*str) && bufpos < buffer + size && 
  509.           GetCharacter(str) == *bufpos)
  510.           {
  511.         str += 2; ++bufpos;
  512.       }
  513.       if(!isxdigit(*str))
  514.         pattern = str;    /* exits while loop */
  515.       else
  516.         bufpos = errpos; /* reset buffer */
  517.         }
  518.         else
  519.       return MATCHERR_NO_MATCH;
  520.       }
  521.       break;
  522.     default: return MATCHERR_NO_MATCH; break;
  523.     }
  524.   }
  525.   return 0;
  526. }
  527.  
  528. ULONG MatchBufPattern(STRPTR pattern, STRPTR buffer, ULONG size, ULONG fsize)
  529. {
  530.   ULONG err = MATCHERR_NO_MATCH;
  531.  
  532.   if(!pattern || CheckBufPattern(pattern))
  533.   {
  534. #ifdef DEBUG
  535.     Printf("MatchBufPattern: CheckBufPattern(%s) failed\n", pattern);
  536. #endif
  537.     return MATCHERR_PATTERN_INCORRECT;
  538.   }
  539.  
  540.   while(*pattern)
  541.   {
  542.     if(!(err = CheckPattern(pattern, buffer, size, fsize)))
  543.       return 0;
  544.     else /* search for next OR field or end of pattern */
  545.     {
  546.       while(*pattern && *pattern != '|')
  547.         ++pattern;
  548.       if(*pattern == '|')
  549.         ++pattern;
  550.     }
  551.   }
  552.  
  553.   return err;
  554. }
  555.  
  556. ULONG MatchFileName(STRPTR pattern, STRPTR name)
  557. {
  558.   ULONG a, b = MATCHERR_NO_MATCH;
  559.   STRPTR buf;
  560.  
  561.   if(!pattern)
  562.     return MATCHERR_PATTERN_INCORRECT;
  563.  
  564.   a = (strlen(pattern)<<1) + 10; /* pattern match buffer */
  565.  
  566.   if(!(buf = (STRPTR) AllocMem(a, MEMF_ANY)))
  567.     return MATCHERR_NO_MEMORY;
  568.  
  569.   if(ParsePatternNoCase(pattern, buf, a) >= 0 && MatchPatternNoCase(buf, name))
  570.     b = 0;
  571.  
  572.   FreeMem(buf, a);
  573.  
  574.   return b;
  575. }
  576.  
  577. struct XpkTypeData * __asm RecogFunc(register __a0 STRPTR buf,
  578. register __a1 STRPTR name, register __d0 ULONG bufsize,
  579. register __d1 ULONG fullsize, register __a2 struct TagItem *tags)
  580. {
  581.   struct XpkPrefsSemaphore *sem;
  582.   struct XpkTypePrefs *xp;
  583.   struct Node *n;
  584.  
  585. #ifdef DEBUG
  586.   if(tags)
  587.   {
  588.     while(tags->ti_Tag)
  589.       VPrintf("%ld %ld\n", tags++);
  590.   }
  591. #endif
  592.  
  593.   if(!buf || !bufsize)
  594.     return 0;
  595.  
  596.   sem = (struct XpkPrefsSemaphore *) FindSemaphore(XPKPREFSSEMNAME);
  597.   /* I can do without ObtainSemaphore, because when I'm called here the
  598.   semaphore is owned already and surely exists */
  599.  
  600.   if(sem->xps_PrefsData)
  601.   {
  602.     for(n = ((struct XpkStdSemaphoreData *)sem->xps_PrefsData)->
  603.       xssd_TypeList.lh_Head; n->ln_Succ; n = n->ln_Succ)
  604.     {
  605.       xp = &((struct XpkTypeNode *) n)->xtn_TypePrefs;
  606.  
  607.       if((name && xp->xtp_Flags & XPKT_NamePattern) ||
  608.       xp->xtp_Flags & XPKT_FilePattern)
  609.       {
  610.         if(!(xp->xtp_Flags & XPKT_FilePattern) || !MatchBufPattern(
  611.         xp->xtp_FilePattern, buf, bufsize, fullsize))
  612.         {
  613.           if(!name || !(xp->xtp_Flags & XPKT_NamePattern) || !MatchFileName(
  614.           xp->xtp_NamePattern, name))
  615.       {
  616. #ifdef DEBUG
  617.             Printf("RecogFunc: matched '%s'\n", xp->xtp_TypeName);
  618. #endif
  619.             return xp->xtp_PackerData;
  620.       }
  621. #ifdef DEBUG
  622.           else
  623.             Printf("RecogFunc: no namematch '%s'\n", xp->xtp_TypeName);
  624. #endif
  625.         }
  626. #ifdef DEBUG
  627.         else
  628.           Printf("RecogFunc: no bufmatch '%s'\n", xp->xtp_TypeName);
  629. #endif
  630.       }
  631. #ifdef DEBUG
  632.       else
  633.         Printf("RecogFunc: no patterns '%s'\n", xp->xtp_TypeName);
  634. #endif
  635.     }
  636.   }
  637.  
  638.   if(sem->xps_MainPrefs)
  639.     return sem->xps_MainPrefs->xmp_DefaultType;
  640.  
  641.   return 0;
  642. }
  643.  
  644.